package com.ruoyi.basic.service.impl;

import cn.hutool.extra.pinyin.PinyinUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.basic.domain.TbCategory;
import com.ruoyi.basic.mapper.TbCategoryMapper;
import com.ruoyi.basic.service.ITbCategoryService;
import com.ruoyi.basic.service.ITbDailyUnitPriceService;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.Ztree;
import com.ruoyi.common.enums.BizExceptionEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * 分类Service业务层处理
 * 
 * @author ruoyi
 * @date 2022-09-04
 */
@Service
public class TbCategoryServiceImpl extends ServiceImpl<TbCategoryMapper, TbCategory> implements ITbCategoryService
{
    @Autowired
    private ITbDailyUnitPriceService dailyUnitPriceService;
    @Override
    public List<TbCategory> listByCondition(TbCategory tbCategory) {
        LambdaQueryWrapper<TbCategory> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(ObjectUtils.isNotEmpty(tbCategory.getName()),TbCategory::getName,tbCategory.getName())
        .eq(ObjectUtils.isNotEmpty(tbCategory.getStatus()),TbCategory::getStatus,tbCategory.getStatus());
        return list(wrapper);
    }

    @Override
    public boolean deleteByIds(String ids) {
        if(ObjectUtils.isEmpty(ids)){
            throw new ServiceException(BizExceptionEnum.REQUEST_PARAMETER_ERROR.getMessage());
        }
        LambdaQueryWrapper<TbCategory> wrapper = new LambdaQueryWrapper();
        wrapper.in(TbCategory::getId,Arrays.asList(ids.split(",")));
        return remove(wrapper);
    }

    @Override
    public String checkCategoryNameUnique(TbCategory tbCategory) {
        Long categoryId = StringUtils.isNull(tbCategory.getId()) ? -1L : tbCategory.getId();
        TbCategory info = checkCategoryNameUnique(tbCategory.getName(), tbCategory.getParentId());
        if (StringUtils.isNotNull(info) && info.getId().longValue() != categoryId.longValue())
        {
            return UserConstants.CATEGORY_NAME_NOT_UNIQUE;
        }
        return UserConstants.CATEGORY_NAME_UNIQUE;
    }

    @Override
    public int selectNormalChildrenCategoryById(Long categoryId) {
        return baseMapper.selectNormalChildrenCategoryById(categoryId);
    }

    @Override
    public int selectCategoryCount(Long parentId) {
        LambdaQueryWrapper<TbCategory> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TbCategory::getDelFlag,"0")
                .eq(ObjectUtils.isNotEmpty(parentId),TbCategory::getParentId,parentId);
        return (int)count(wrapper);
    }

    @Override
    public boolean checkCategoryExistDailyUnitPrice(Long id) {
        return dailyUnitPriceService.checkCategoryExistByCategoryId(id);
    }

    @Override
    public List<Ztree> selectCategoryTree(TbCategory category) {
        List<TbCategory> categoryList = listByCondition(category);
        List<Ztree> ztrees = initZtree(categoryList);
        return ztrees;
    }

    @Override
    public List<Ztree> selectDeptTreeExcludeChild(TbCategory category) {
        Long excludeId = category.getExcludeId();
        List<TbCategory> categoryList = listByCondition(category);
        Iterator<TbCategory> it = categoryList.iterator();
        while (it.hasNext())
        {
            TbCategory c = (TbCategory) it.next();
            if (c.getId().intValue() == excludeId
                    || ArrayUtils.contains(StringUtils.split(c.getAncestors(), ","), excludeId + ""))
            {
                it.remove();
            }
        }
        List<Ztree> ztrees = initZtree(categoryList);
        return ztrees;
    }

    @Override
    public boolean saveCategory(TbCategory tbCategory) {
        if (UserConstants.CATEGORY_NAME_NOT_UNIQUE.equals(checkCategoryNameUnique(tbCategory)))
        {
            throw new ServiceException("新增分类'" + tbCategory.getName() + "'失败，分类名称已存在");
        }
        TbCategory info = getById(tbCategory.getParentId());
        // 如果父节点不为正常状态,则不允许新增子节点
        if (info != null && !UserConstants.CATEGORY_NORMAL.equals(info.getStatus())) {
            throw new ServiceException("部门停用，不允许新增");
        }
        if (info != null) {
            Long max = getMax()+1;
            tbCategory.setCode(String.valueOf(tbCategory.getParentId())+max);
            tbCategory.setLevel(info.getLevel()+1);
            tbCategory.setAncestors(info.getAncestors() + "," + tbCategory.getParentId());
        } else {
            tbCategory.setCode(Constants.CATEGORY_DEFAULT_CODE);
            tbCategory.setLevel(1);
            tbCategory.setAncestors("0");
        }
        return save(tbCategory);
    }

    private Long getMax() {
        LambdaQueryWrapper<TbCategory> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(TbCategory::getId);
        return list(wrapper).get(0).getId();
    }

    @Override
    public boolean updateCategory(TbCategory tbCategory) {
        Long categoryId = tbCategory.getId();
        if (UserConstants.CATEGORY_NAME_NOT_UNIQUE.equals(checkCategoryNameUnique(tbCategory)))
        {
            throw new ServiceException("修改分类'" + tbCategory.getName() + "'失败，分类名称已存在");
        }
        else if (tbCategory.getParentId().equals(categoryId))
        {
            throw new ServiceException("修改分类'" + tbCategory.getName() + "'失败，上级分类不能是自己");
        }
        else if (StringUtils.equals(UserConstants.CATEGORY_DISABLE, tbCategory.getStatus())
                && selectNormalChildrenCategoryById(categoryId) > 0)
        {
            throw new ServiceException("该分类包含未停用的子分类！");
        }
        boolean result = false;
        TbCategory newParentCategory = getById(tbCategory.getParentId());
        TbCategory oldCategory = getById(tbCategory.getId());
        if (StringUtils.isNotNull(newParentCategory) && StringUtils.isNotNull(oldCategory)) {
            String newAncestors = newParentCategory.getAncestors() + "," + newParentCategory.getId();
            String oldAncestors = oldCategory.getAncestors();
            tbCategory.setAncestors(newAncestors);
            updateCategoryChildren(tbCategory.getId(), newAncestors, oldAncestors);
        }
        result = updateById(tbCategory);
        if (UserConstants.DEPT_NORMAL.equals(tbCategory.getStatus())) {
            // 如果该部门是启用状态，则启用该分类的所有上级分类
            result = updateParentCategoryStatus(tbCategory);
        }
        return result;
    }

    @Override
    public TbCategory getCategoryById(Long id) {
        TbCategory category = getById(id);
        if(ObjectUtils.isEmpty(category.getParentId())){
            return category;
        }
        if (Long.valueOf(100L).equals(id))
        {
            category.setParentName("无");
        }else {
            TbCategory parentCategory = getById(category.getParentId());
            category.setParentName(parentCategory.getName());
        }
        return category;
    }

    private boolean updateParentCategoryStatus(TbCategory tbCategory) {
        LambdaUpdateWrapper<TbCategory> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(TbCategory::getStatus,tbCategory.getStatus())
        .eq(TbCategory::getId,tbCategory.getId());
        return update(wrapper);
    }

    /**
     * 修改子元素关系
     *
     * @param categoryId       被修改的分类ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updateCategoryChildren(Long categoryId, String newAncestors, String oldAncestors) {
        List<TbCategory> children = baseMapper.selectChildrenCategoryById(categoryId);
        for (TbCategory child : children) {
            child.setAncestors(child.getAncestors().replace(oldAncestors, newAncestors));
        }
        if (children.size() > 0) {
            baseMapper.updateCategoryChildren(children);
        }
    }

    /**
     * 对象转分类树
     *
     * @param categoryList 分类列表
     * @return 树结构列表
     */
    public List<Ztree> initZtree(List<TbCategory> categoryList)
    {
        return initZtree(categoryList, null);
    }

    /**
     * 对象转分类树
     *
     * @param categoryList 分类列表
     * @param roleDeptList 角色已存在菜单列表
     * @return 树结构列表
     */
    public List<Ztree> initZtree(List<TbCategory> categoryList, List<String> roleDeptList)
    {

        List<Ztree> ztrees = new ArrayList<Ztree>();
        boolean isCheck = StringUtils.isNotNull(roleDeptList);
        for (TbCategory category : categoryList)
        {
            if (UserConstants.CATEGORY_NORMAL.equals(category.getStatus()))
            {
                Ztree ztree = new Ztree();
                ztree.setId(category.getId());
                ztree.setpId(category.getParentId());
                ztree.setName(category.getName());
                ztree.setTitle(category.getName());
                if (isCheck)
                {
                    ztree.setChecked(roleDeptList.contains(category.getId() + category.getName()));
                }
                ztrees.add(ztree);
            }
        }
        return ztrees;
    }

    private TbCategory checkCategoryNameUnique(String name, Long parentId) {
        LambdaQueryWrapper<TbCategory> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TbCategory::getDelFlag,"0")
                .eq(ObjectUtils.isNotEmpty(name),TbCategory::getName,name)
                .eq(ObjectUtils.isNotEmpty(parentId),TbCategory::getParentId,parentId)
                .orderByDesc(TbCategory::getCreateTime);
        List<TbCategory> list = list(wrapper);
        return list.isEmpty() ? null : list.get(0);
    }

}
